-ifndef(KATZENREIS_HRL).
-define(KATZENREIS_HRL, true).

-define(FLOAT_PATTERN, "^(\\+|-)?[0-9]+\\.[0-9]+((E|e)(\\+|-)?[0-9]+)?").
-define(INT_PATTERN, "^(\\+|-)?[0-9]+").
-define(STR_PATTERN, "^\"(\\\\\"|[^\"])*\"").
-define(IDENT_PATTERN, "^[a-z][0-9a-zA-Z_\\.]*").
-define(ARG_PATTERN, "((" ?STR_PATTERN ")"
                     "|(" ?FLOAT_PATTERN ")"
                     "|(" ?INT_PATTERN ")"
                     "|(" ?IDENT_PATTERN "))").

-define(TABLE, 'katzenreis').
-define(CUSTOM_FILTER_TABLE, 'katzenreis:custom_filters').
-define(CUSTOM_TAG_TABLE, 'katzenreis:custom_tags').
-define(CUSTOM_TEXT_RENDERERS, 'custom_text_renderers').

-define(DEFAULT_VALUE, "").

-define(AUTOESCAPE_VAR, 'autoescape').
-define(COUNTER_VAR, 'counter').
-define(COUNTER0_VAR, 'counter0').
-define(FIRST_VAR, 'first').
-define(FORLOOP_VAR, 'forloop').
-define(LAST_VAR, 'last').
-define(PARENTLOOP_VAR, 'parentloop').
-define(REVCOUNTER_VAR, 'revcounter').
-define(REVCOUNTER0_VAR, 'revcounter0').

-define(SAFE_ATTR, 'safe').

%% @type proplist() = [{atom(), any()}].
%%  Property list.
%% @type context() = proplist().
%% @type options() = proplist().
%%  Rendering options.

-type(proplist() :: [{atom(), any()}]).
-type(context() :: proplist()).
-type(options() :: proplist()).


%% @type attributes() = proplist().
%%  Attributes of texts to render.
%%
%%  <dl>
%%  <dt><code>{safe, boolean()}</code></dt>
%%  <dd>
%%  If the value is `true', the string does not need to be escape
%%  HTML control characters even if <code>autoescape</code> is <code>on</code>.
%%  </dd>
%%  </dl>

-type(attributes() :: proplist()).


%% @type func_info() = {Module::atom(), Function::atom()}.
%%  A tuple of module name and function name.
%%
%% @type filter_name() = atom().
%%  Filter name.
%%
%% @type filter_arg() = string() | 'nil'.
%%  Filter argument. `nil' means that a filter has no argument.
%%
%% @type filter() = function((Value::term(), Attrs::attributes(),
%%  Arg::filter_arg(), context(), options()) -> any()).
%%  Filter callback.
%%  The function returns a value converted `Value' with
%%  a filter argument `Arg'.

-type(func_info() :: {atom(), atom()}).
-type(filter_name() :: atom()).
-type(filter_arg() :: string() | 'nil').
% -type(filter() :: fun((term(), attributes(), filter_arg(), context(), options()) -> any())).


%% @type line_number() = integer().
%%  Line number.
%%
%% @type var_name() = atom().
%%  Variable name.
%%
%% @type tag_name() = atom() | '$end'.
%%  Tag name.
%%
%% @type tag_arg() = string().
%%  Tag argumnt. The string is parsed by tag renderer.
%%
%% @type arith() = integer().
%%  Number of arguments.
%%
%% @type filter_token() = {line_number(), filter_name(), filter_arg()}.
%%  Filter information.
%%
%% @type template_node() =
%%  {'text', line_number(), string()} |
%%  {'var', line_number(), var_name(), [filter_token()]} |
%%  {'tag', line_number(), tag_name(), [{line_number(), tag_arg()}]}.
%%
%%  Template node. Node type is one of `text', `var' or `tag'.
%%
%%  <li>
%%  `text': Text node represents text which is appended to result.
%%  </li>
%%  <li>
%%  `var': Variable node represents a variable which gets replaced itself
%%  with value %%  when the template is evaluated.
%%  </li>
%%  <li>
%%  `tag': Tag node represents a tag which controls the logic of the template.
%%  </li>
%%
%% @type tag_parser() = function((Args::[string()],
%%  Nodes::[template_node()],
%%  Options::options()) -> {TagNodes::[template_node()],
%%  Rest::[template_node()]}).
%%  Callback function to parse nodes used by custom tags.
%%  It must return a tuple of the nodes and the rest nodes.
%%
%% <dl>
%% <dt><code>Args</code></dt>
%% <dd>Arguments of custom tags.</dd>
%% </dl>
%%
%% @type tag_renderer() = function((Nodes::[template_node()],
%%  Context::context(),
%%  Options::options()) -> any()).
%%  Callback function to render custom tag nodes.
%%  It must return value to replace the nodes in evaluated template.

-type(line_number() :: pos_integer()).
-type(var_name() :: atom()).
-type(tag_name() :: atom() | '$end').
-type(tag_arg() :: string()).
-type(arith() :: pos_integer()).
-type(filter_token() :: {line_number(), filter_name(), filter_arg()}).
-type(template_node() ::
        {'text', line_number(), string()} |
        {'var', line_number(), var_name(),
            [{line_number(), filter_name(), filter_arg()}]} |
        {'tag', line_number(), tag_arg(), [{line_number(), tag_arg()}]}).

% -type(tag_parser() :: fun(([string()], [template_node()], options()) ->
%   {[template_node()], [template_node()]})).
% -type(tag_renderer() :: fun(([template_node()], context(), options()) ->
%   any())).

-endif. % KATZENREIS_HRL

